from twisted.application import service, internet
from twisted.internet import reactor
from twisted.internet import defer
from twisted.python import log
from nevow import athena, loaders, tags
from nevow import appserver
from nevow import flat

from stickies.templates import template_dir

class BoardRoom(object):
    clients = []
    notecards = {}

    def makeBoard(self):
        element = BoardElement(self)
        self.clients.append(element)
        return element

    def added_notecard(self, board, note_id):
        """Add a notecard created by the client
        represented by board to other clients"""
        for client in self.clients:
            if client is not board:
                log.msg("adding card %s to client %s"%(note_id, board),
                        debug=True)
                client.callRemote('add_notecard', note_id)

    def update_positions(self, note_id, left, top):
        print "BoardRoom: updating", note_id, left, top

        note_id = int(note_id)
        self.notecards[note_id]["left"] = left
        self.notecards[note_id]["top"] = top

        print "notifying other clients to update their position"
        for client in self.clients:
            print "remote:","update_position", note_id, left, top
            client.callRemote("update_position", note_id, left, top)

board = BoardRoom().makeBoard

class BoardElement(athena.LiveElement):
    jsClass = u'Stickies.Board'

    docFactory = loaders.xmlfile(
        templateDir=template_dir, template="board.html"
    )

    def __init__(self, room): #*a, **kw):
        #super(BoardElement, self).__init__(*a, **kw)
        #reactor.callLater(5, self.myEvent)
        self.room = room

    def load_board(self):
        log.msg("Loading %s..."%(self), debug=True)
        deferreds = []
        for note_id in self.room.notecards:
            log.msg("Loading notecard %s: left %s; top %s"%(note_id,
                                           self.room.notecards[note_id]['left'],
                                           self.room.notecards[note_id]['top']),
                                           debug=True)
            d = self.callRemote("add_notecard", int(note_id))
            d.addCallback(
                self.callRemote,
                "position_notecard",
                unicode(str(note_id)),
                unicode(str(self.room.notecards[note_id]['left'])),
                unicode(str(self.room.notecards[note_id]['top']))
            )
            d.addErrback(self.echo)
            deferreds.append(d)
        deferredList = defer.DeferredList(deferreds)

        #deferredList.addCallback(self.echo)
        #deferredList.addErrback(self.echo)

        return deferredList
    athena.expose(load_board)

    def myEvent(self):
        print "My Event Firing"
        self.callRemote("echo", 12345)

    def echo(self, argument):
        message = unicode(str(argument))
        print "Echoing", message
        return message
    athena.expose(echo)

    def created_notecard(self, note_id, left, top):
        log.msg(
            'CREATED_NOTECARD CALLED WITH %s, %s, %s' % (note_id, left, top),
            debug=True
        )
        log.msg('BEFORE CREATE: ROOM(%s): %s'%(len(self.room.notecards),
                                self.room.notecards.keys()),
                debug=True)
        self.room.notecards[note_id] = {u'note_id': note_id, u'left': left, u'top': top}
        log.msg('AFTER CREATE: ROOM(%s): %s'%(len(self.room.notecards),
                                self.room.notecards.keys()),
                debug=True)
        self.room.added_notecard(self, note_id)

    athena.expose(created_notecard)

    def add_notecard(self):
        self.room.add_notecard()
    athena.expose(add_notecard)

    def update_position(self, u, left, top):
        print "Entering: update_position"
        i = str(u)
        parts = i.split(":")
        i = parts[-1]
        print "i, left, top:",i, left, top
        self.room.update_positions(i, left, top)
    athena.expose(update_position)
